from openpyxl import load_workbook
from math import ceil
import sys
sys.path.append("..")
from functional.utils import SPLIT_FUNC_DICT, JOIN_STR_DICT, EXTRACT_FUNC_DICT, REPLACE_FULLNAME_FUNC_DICT
from traceback import format_exc

def name_into_parts(name):
	# 若有斜杠，则提取斜杠之前的
	if "/" in name:
		name = name.split("/")[0]
	else:
		# 若有括号，则提取左括号之前的
		if "(" in name:
			name = name.split("(")[0]

	name = name.strip()
	# 若名称中有，则按","分割，否则按空格分割
	if "," in name:
		res = name.split(",")
	else:
		res = name.split(" ")

	# 检查分割后有没有左括号，若有则提取出出左括号之前的
	tmp = []
	for i in res:
		if "(" in i:
			i = i.split("(")[0]
		tmp.append(i.strip())
	return tmp

def check_matched(author_parts, fullname_parts):
	author_parts_len = len(author_parts)
	fullname_parts_len = len(fullname_parts)

	# 长度不一致，直接匹配失败
	if author_parts_len != fullname_parts_len:
		return False

	# 不足两段
	if author_parts_len < 2 or fullname_parts_len < 2:
		# 理论上不存在这种情况
		if author_parts_len == 0:
			return False

		# 简称和全称相同，匹配以获取全称
		if author_parts[0] == fullname_parts[0]:
			return True

		return False

	for sur in range(2):
		for fullname_sur in range(2):
			not_sur = 1-sur
			fullname_not_sur = 1-fullname_sur

			if author_parts[sur] == fullname_parts[fullname_sur]:
				if author_parts[not_sur] == "" or fullname_parts[fullname_not_sur] == "":
					if author_parts[not_sur] == fullname_parts[fullname_not_sur]:
						return True
				else:
					if author_parts[not_sur][0] == fullname_parts[fullname_not_sur][0]:
						return True
	return False

def match_fullname(author, fullname_list):
	author_parts = name_into_parts(author)
	for fullname in fullname_list:
		if check_matched(author_parts, fullname[0]):
			return fullname[1]
	return author

def match_fullnames(author_list, fullname_list):
	res = []
	for author in author_list:
		res.append(match_fullname(author, fullname_list))
	return res

def bind_fullname_in_single_record(addr, addr_list, fullname_list, extract_func, replace_func):
	res = []
	for addr in addr_list:
		author_list = extract_func(addr)
		matched_fullnames = match_fullnames(author_list, fullname_list)
		res.append(replace_func(addr, matched_fullnames))
	return res

def split_fullnames_into_parts(fullname_list):
	res = [(name_into_parts(fullname), fullname) for fullname in fullname_list]
	return res

def get_fullname_list(fullname_str):
	if fullname_str == None or fullname_str == "":
		return []
	res = fullname_str.split(";")
	res = [i.strip() for i in res if i != ""]
	return split_fullnames_into_parts(res)

def bind_fullname_func(args):
	try:
		workbook_file_name = args[0]
		output_file_name = args[1]
		sheet_name = args[2]
		row_from = args[3]
		row_to = args[4]
		data_cols = args[5]
		fullname_col = args[6]
		signal = args[7]
		
		signal.emit("启动全名绑定任务\n开始加载EXCEL文件")

		wb = load_workbook(workbook_file_name)
		sh = wb[sheet_name]

		signal.emit("完成EXCEL文件加载\n开始绑定全名")

		length = row_to - row_from + 1
		step = ceil(length*0.1)

		for data_col in data_cols:
			input_col = data_col[1]
			output_col = data_col[2]
			addr_type = data_col[3]

			split_func = SPLIT_FUNC_DICT[addr_type]
			join_str = JOIN_STR_DICT[addr_type]
			extract_func = EXTRACT_FUNC_DICT[addr_type]
			replace_func = REPLACE_FULLNAME_FUNC_DICT[addr_type]

			if row_from > 1:
				sh.cell(row_from-1, output_col).value = data_col[0]


			for i in range(row_from, row_to+1):
				try:
					addr_str = sh.cell(i, input_col).value
					fullname_str = sh.cell(i, fullname_col).value

					addr_list = split_func(addr_str)
					fullname_list = get_fullname_list(fullname_str)
					addr_list = bind_fullname_in_single_record(addr_str, addr_list, fullname_list, extract_func, replace_func)
					
					sh.cell(i, output_col).value = join_str.join(addr_list)

					cnt = i - row_from + 1
					if cnt % step == 0:
						signal.emit(f"{data_col[0]}: {cnt/length*100:.2f}%")
				except Exception as e:
					e.args = (f"{e.args[0]}在处理行{i}的数据时",)
					raise e
		
		signal.emit("完成全名绑定\n开始写入结果")
		wb.save(output_file_name)
		signal.emit("完成结果写入")

	except Exception as e:
		signal = args[7]
		signal.emit(f"绑定失败：{e}\n追踪信息：{format_exc()}")

if __name__ == "__main__":
	addr_type = "SCOPUS一般地址"
	fullname_list = get_fullname_list(input())
	print(fullname_list)
	print()
	addr = input()
	addr_list = SPLIT_FUNC_DICT[addr_type](addr)
	print(addr_list)
	print()
	print(bind_fullname_in_single_record(addr, addr_list, fullname_list, EXTRACT_FUNC_DICT[addr_type], REPLACE_FULLNAME_FUNC_DICT[addr_type]))